package com.snail.model.pojo;

import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.elasticsearch.core.search.Hit;
import co.elastic.clients.elasticsearch.core.search.HitsMetadata;
import lombok.Data;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author cici
 * @description 因为查询数据需要存进redis当中，springboot当中的SearchResponse没有提供序列化方案，又不想动原来的代码，这里手动封装一个查询结果
 * 这里说明一下SearchResponse和SearchHint的结构
 *和kibanan当中的数据结构基本一致
 *其中SearchHint获取的数据为第一层的hit的数据，包括，{total": {"value":,"relation": },"max_score": ,hits{"_index",_id,_score,source{具体的商品信息}}。
 * SearchHint的获取值方法全用get方法
 * 而SearchResponse包含所有的数据，通过.可以看出获取其值的方式
 * @date 2025/8/14 15:31
 */
@Data
public class SearchHitResult<T>  {
    private Long took;
    private boolean timedOut;
    private Long totalHits;
    private List<Document<T>> hits;


    @Data
    public static class Document <T> implements Serializable {
        private String index;
        private String id;
        private Double score;
        private T source;
    }

    // 构造函数
    public SearchHitResult() {
        this.hits = new ArrayList<>();
    }

    public SearchHitResult(Long took, boolean timedOut, Long totalHits, List<Document<T>> hits) {
        this.took = took;
        this.timedOut = timedOut;
        this.totalHits = totalHits;
        this.hits = hits;
    }

    /**
     * 使用 SearchHits 对象进行赋值的静态工厂方法
     * @param searchResponse Elasticsearch 搜索结果中的 SearchHits 对象
     * @return 封装好的 SearchHitResult 对象
     */
    public static <T> SearchHitResult<T> fromSearchHits(SearchResponse<T> searchResponse) {
        SearchHitResult<T> result = new SearchHitResult<>();
        // 赋值基本信息
        result.setTook(searchResponse.took());
        result.setTimedOut(searchResponse.timedOut());
        HitsMetadata searchHits = searchResponse.hits();//第一层的hits，包含了total，max，hits，其中hits当中的数据才是想要的数据
        // 遍历并提取 hits，先赋值查到的总数。再赋值第二层的hits
        if (searchHits != null) {
            // 设置总命中数
            if (searchHits.total().value() != 0) {
                result.setTotalHits(searchHits.total().value());
            }
            // 遍历并封装每个文档
            // 转换每个hit
            List<SearchHitResult.Document> documents = new ArrayList<>();
            List<Hit<T>> document = null;
            SearchHitResult outer = new SearchHitResult();
            //SearchHitResult.Document dup=outer.new Document();
            for (Object item : searchResponse.hits().hits()) {

                Hit<T> hit =(Hit<T>) item;
                //System.out.println("hit"+hit.toString());
                // 每次循环都新建一个 Document 对象
                Document<T> dup = new Document<>();
                dup.setSource(hit.source());
                dup.setId(hit.id());
                dup.setScore(hit.score());
                dup.setIndex(hit.index());


                result.hits.add(dup);  // 现在可以安全添加
            }

            return result;

        }

        return result;
    }


}
